package com.ruoyi.framework.mdc;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 链路跟踪拦截器  用于 restTemplate增加请求头
 *
 * @Author： Lonni
 * @Date： 2025/9/9  15:23
 */
@Component
@Slf4j
public class TraceInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        log.info("进入TraceInterceptor=====>,准备发起外部服务调用");
        // 从MDC获取跟踪信息
        String traceId = MDC.get(MdcConstain.TRACE_ID);
        String spanId = MDC.get(MdcConstain.SPAN_ID);
        log.info("链路跟踪信息: traceId={}, spanId={}", traceId, spanId);
        // 将跟踪信息添加到请求头
        if (traceId != null) {
            request.getHeaders().add(MdcConstain.TRACE_ID_HEADER, traceId);
        }

        if (spanId != null) {
            request.getHeaders().add(MdcConstain.SPAN_ID_HEADER, spanId);
            // 当前span作为父span传递给下游服务
            request.getHeaders().add(MdcConstain.PARENT_SPAN_ID_HEADER, spanId);
        }
        long startTime = System.currentTimeMillis();
        request.getHeaders().add(MdcConstain.PROCESS_TIME,String.valueOf(startTime));
        // 记录请求开始时间

        // 执行请求
        ClientHttpResponse response = execution.execute(request, body);

        // 记录请求耗时
        long duration = System.currentTimeMillis() - startTime;

        // 记录调用信息
        if (traceId != null) {
            MDC.put("traceId", traceId);
        }

        // 使用SLF4J记录调用信息，确保日志中包含跟踪信息
        org.slf4j.LoggerFactory.getLogger(TraceInterceptor.class)
                .info("调用外部服务: {} {}, 状态码: {}, 耗时: {}ms",
                        request.getMethod(), request.getURI(),
                        response.getStatusCode(), duration);

        return response;


    }
}
